﻿/*******************************************************************************
牛牛浏览器控件的JS部分的核心流程 请勿修改 
*******************************************************************************/


var emClosed = 1;
var emConnected = 2;
var emConnecting = 3;

var emcontrolSuccess = 0;
var emcontrolFailed = 1;
var emcontrolUnknown = 2;


var controlObjSelf = null;

function isMacintosh() 
{
  return navigator.platform.indexOf('Mac') > -1;
}

function onWebControlPluginLoaded()
{
    controlObjSelf.pluginLoaded();
}

function NiuniuControlObject(hostPort, controlName, controlFlag, webcontrolAuth) 
{
    var self = this;
    controlObjSelf = this;
    
	this.NiuniuAuthKey = "";
	this.identifier = "";
	
	this.isEnableWebSocket = true;		//是否启用websocket，表示是否要支持chrome，firefox，edge，猎豹等浏览器 	
	
    this.hostPortIndex = 0;  
    this.NiuniuSocket = null;
    this.connectState = emClosed;
	
    this.IsWaitCustomizedCallBack = false;
	this.autoConnectAfterPageLoad = true;
	this.IsFirstConnect = true;
	this.IsEverConnected = false;
	
	this.reconnectTryTime = 0;
    this.TimeIntervalID = -1;
	this.ReceivedEchoBack = false;
	this.SocketTimeStamp = new Date().getTime();
	this.TimeOutID = -1;
	
    this.InvokeCallback = null;
    this.PluginLoadedCallback = null;
	this.OnConnectFailed = null;
	
	this.webcontrolAuth = webcontrolAuth;
	this.hostPort = hostPort;				//从上级使用JS中设置好，用于连接控件 
    this.controlName = controlName;			//从上级使用JS中设置好, 用于浏览器自定义协议
	this.webcontrolobjecttype = controlFlag;	//从上级使用JS中设置好，用于activex及npapi
	
	
	this.openlocalframeid = "startcontrolFrame";
	this.controlcontainerid = "niuniuwebcontrolcontainer";
	this.webcontrolid = "niuniucontrol";
	
    this.LoadPlugin = function()
    {
		if(self.webcontrolobjecttype == '')
		{
			alert("webcontrolobjecttype can not be empty.")
			return;
		}
        var obj = $('#' + self.controlcontainerid);
        if(obj.length < 1)
        {
            $("body").append('<div id="' + self.controlcontainerid + '" style="height:0px;width:0px;"></div>');
            obj = $('#' + self.controlcontainerid);
        }        
        obj.html('');
        obj.html('<object id="' + self.webcontrolid + '" type="' + self.webcontrolobjecttype + '" width="0" height="0"><param name="onload" value="onWebControlPluginLoaded" /></object>');
		
		var iframeObj = $('#' + self.openlocalframeid);
		if(iframeObj.length < 1)
		{
			$("body").append('<iframe id="' + self.openlocalframeid + '" style="display:none;"></iframe>');			
		}
		
		setTimeout("controlObjSelf.checkPlugin();", 1500);
    }
    
    this.niuniucontrol = function ()
    {
        return document.getElementById(self.webcontrolid);
    }
        
    this.addEvent = function(obj, name, func)
    {
        if (obj.attachEvent) {
            obj.attachEvent("on"+name, func);
        } else {
            obj.addEventListener(name, func, false); 
        }
    }
    
	this.isUseful = function()
	{
		if(self.pluginValid())
			return true;
		if(self.NiuniuSocket != null && self.connectState == emConnected)
		{
			return true;
		}
		return false;
	}
	
    this.pluginValid = function()
    {
        try
        {
            if(self.niuniucontrol().valid)
            {
                return true;
            }
        }
        catch(e)
        {
        }
        return false;        
    }

       
    this.OnInvokeCallback = function(type, obj) 
    {
        if(self.InvokeCallback != null)
        {
            self.InvokeCallback(type, obj);
        }
        else
        {
            alert("事件未绑定，请指定InvokeCallback回调函数");
        }
    }
    
	this.checkPlugin = function()
	{
		if(!self.isUseful())
		{
			self.PluginLoadedCallback(false);
		}
	}
	
    this.pluginLoaded = function()
    {
		//添加控件的事件监听 
		if(self.pluginValid())
        {
			self.addEvent(self.niuniucontrol(), 'invokeCallback', function(type, content){
				var obj = eval("(" + content + ")");
				self.OnInvokeCallback(obj, content);
			});
        }  
    			
    	if(self.PluginLoadedCallback != null)
        {
            self.PluginLoadedCallback(true);
        }
    }
    
    this.doInvoke = function(params, connIfNotConnected)
	{
	    if(self.IsNeedCustomizedProtocol())
        {
            return self.doInvokeForCustomize(params, connIfNotConnected);
        }
        
        if(!self.pluginValid())
        {
            return emcontrolFailed;
        }
        self.niuniucontrol().invokeMethod(params);
        return emcontrolSuccess; 
	}
		
    this.doInvokeForCustomize = function(params, connIfNotConnected)
    {
	    try
	    {
			if(self.controlName == '')
			{
				alert("controlName can not be empty.");
				return;
			}
    		//启动客户端，或者通过websocket去发送数据   
    		if(self.connectState == emConnected)
    		{
    		    self.NiuniuSocket.send('1' + encodeURIComponent(params) );
    		}
		    else
		    {
				if(!connIfNotConnected)
				{
					return emcontrolUnknown;
				}
				
				self.WriteLog(params.length);
				var newUrl = self.controlName + "://" + encodeURIComponent(params);
				self.WriteLog(newUrl.length);
				
		        //启动客户端  
				$('#' + self.openlocalframeid).attr('src', newUrl);
		        
		        self.IsWaitCustomizedCallBack = true;
				
				self.connectHost();
				return emcontrolUnknown;
		    }		    
	        return emcontrolSuccess;
	    }
	    catch(e)
	    {
    		alert(e.message);
	    }  
	    return emcontrolUnknown;       
    }
		
    this.InitNiuniucontrol = function()
    {
        self.LoadPlugin();
	    setTimeout("controlObjSelf.InitWebSocketAndBindCallback();", 200);
    }
        
    this.InitWebSocketAndBindCallback = function()
    {
		if(!self.autoConnectAfterPageLoad || !self.IsNeedCustomizedProtocol())
		{
			return;
		}
	    self.connectHost();
    }
    
	this.getNextPort = function()
	{
		if(self.hostPort == '')
		{
			alert("hostPort can not be empty.");
			return 30101;
		}
		//进行拆分处理 self.hostPort;
		var portArray = self.hostPort.split(",");
		if(portArray.length < 1)
		{
			alert("hostPort can not be empty.");
			return 30101;
		}
		if(self.hostPortIndex < 0)
		{
			self.hostPortIndex = 0;				
		}
		if(self.hostPortIndex > portArray.length - 1)
		{
			self.hostPortIndex = portArray.length - 1;				
		}
		var nPort = parseInt(portArray[self.hostPortIndex]);
		self.hostPortIndex++;
		if(self.hostPortIndex > portArray.length - 1)
		{
			self.hostPortIndex = 0;				
		}	
		return nPort;
	}
	
    this.connectHost = function()
    {
			if(self.NiuniuSocket != null)
			{
				self.WriteLog("connectHost NiuniuSocket is not null, return.");
				return;
			}
			clearTimeout(self.TimeOutID);
			clearInterval(self.TimeIntervalID);
			self.connectState = emConnecting;
			
			
			try{
				var wshosts = ['127.0.0.1', 'localhost'];
				for (var i in wshosts) {
					try{
						var host = "ws://127.0.0.1:" + self.getNextPort() + "/" + self.controlName;
						self.NiuniuSocket = new WebSocket(host);
						break;
					}
					catch(ee){
						var ggg= 0;
					}
				}
								
				//OutputLog('Socket Status: '+socket.readyState);
				self.NiuniuSocket.onopen = function(evt){					
					self.NiuniuSocket.send('0' + self.SocketTimeStamp);
					self.WriteLog("NiuniuSocket.onopen.");
					clearTimeout(self.TimeOutID);
				}
				
				self.NiuniuSocket.onmessage = function(msg){
					var str = "";
					str = msg.data;
					var id  = str.substr(0, 1);
					var arg1 = str.substr(1);
					clearTimeout(self.TimeOutID);
					if(id == "0"){
						self.hostPortIndex--;
						//表示连接成功，此时应该提示可以使用了 
						self.connectState = emConnected;
						self.pluginLoaded();
						self.IsEverConnected = true;
						self.IsFirstConnect = false;
						if(self.IsWaitCustomizedCallBack)
						{
						    setTimeout("controlObjSelf.SendReadyRecvData();", 3);
						}
						self.WriteLog("connect sucess.");
						self.ReceivedEchoBack = true;
						clearInterval(self.TimeIntervalID);
						self.TimeIntervalID = setInterval("controlObjSelf.LoopEchoMessage()", 3000);
					}
					if(id == "1"){
						//解析消息 
						var retObj = eval("(" + arg1 + ")");
						self.ReceivedEchoBack = true;
						if(retObj.command !== undefined && retObj.command == "echo")
						{					
							//self.WriteLog("received echo");
							return;
						}
						else
						{							
							//self.WriteLog("received controldata.");
							self.OnInvokeCallback(retObj, arg1);			
						}
						
						
					}														
				}
				
				self.NiuniuSocket.onclose = function(evt){					
					self.OnWebSocketError("self.NiuniuSocket.onclose." + evt.data);
				}	
				self.NiuniuSocket.onerror = function (evt) {					
					//self.OnWebSocketError("self.NiuniuSocket.onerror." + evt.data);
				  };
					
			} catch(e){
				self.OnWebSocketError("connect exception." + e.message);
			}
    }
    
	this.WriteLog = function(txt)
	{
		//写日志 
		try{
			console.log(txt);
		}
		catch(e)
		{
			
		}
	}
	
	this.OnWebSocketError = function(type)
	{
		//如果不处于连接成功状态，说明不是断开连接，而是连接失败 
		var isConnectedFailed = false;
		if(self.connectState != emConnected)
		{
			isConnectedFailed = true;
		}
		self.WriteLog(type);
		self.ReceivedEchoBack = false;
		self.connectState = emClosed;		
		
		if(self.NiuniuSocket != null)
		{
			self.NiuniuSocket.close();
		}
		
		self.NiuniuSocket = null;
		clearTimeout(self.TimeOutID);
		clearInterval(self.TimeIntervalID);
		if(isConnectedFailed)
		{
			if(self.IsFirstConnect)
			{
				self.IsFirstConnect = false;
				self.OnConnectFailed(false);	
				return;
			}
			
			if(self.IsEverConnected)
			{
				self.reconnectTryTime++;
				//通知连接连接断开
				if(self.reconnectTryTime > 3)
				{
					self.IsEverConnected = false;
					self.reconnectTryTime = 0;
					self.OnConnectFailed(true);				
					return;
				}
			}
		}
		self.TimeOutID = setTimeout("controlObjSelf.connectHost();", 800);
	}
	
	this.LoopEchoMessage = function()
	{
		if(!self.ReceivedEchoBack)
		{
			self.OnWebSocketError("this.LoopEchoMessage, !self.ReceivedEchoBack");
			self.ReceivedEchoBack = false;
			clearInterval(self.TimeIntervalID);
			self.TimeIntervalID = setInterval("controlObjSelf.LoopEchoMessage()", 3000);
			return;
		}
		self.ReceivedEchoBack = false;
		clearTimeout(self.TimeOutID);
		if(self.connectState != emConnected)
		{
			clearInterval(self.TimeIntervalID);
			return;
		}		
		var obj = new Object(); 
		obj.command = "echo";
		self.NiuniuSocket.send("1" + encodeURIComponent( $.toJSON(obj)) );		
	}
	
    this.SendReadyRecvData = function()
    {
		self.WriteLog("SendReadyRecvData.");
        var obj = new Object();
		obj.CmdType = -1;
		self.NiuniuSocket.send("1" + encodeURIComponent( $.toJSON(obj)) );
    }

    
    
    this.IsNeedCustomizedProtocol = function()
    {
		if(isMacintosh())
		{
			return true;
		}
        if(!self.isEnableWebSocket)
        {
            return false;
        }
        
        if(self.pluginValid())
        {
            return false;
        }
        
        try
        {
            var agent = window.navigator.userAgent.toLowerCase();       
			var isIE = agent.indexOf("compatible") > -1 && agent.indexOf("msie") > -1;
			if(isIE)
			{
				return false;
			}
			
			var isIE11 = agent.indexOf('trident') > -1 && agent.indexOf("rv:11.0") > -1;
			if(isIE11)
			{
				return false;
			}
            var isQQBrowser = agent.indexOf("qqbrowser") != -1;
            //if(isQQBrowser)
            //{
            //    return false;
            //}
			var isUBrowser = agent.indexOf("ubrowser") != -1;
			if(isUBrowser)
            {
                return false;
            }
			
            //如果是firefox 且在50版本以上，则需要             
			var isFirefox = agent.indexOf("firefox") != -1;
			if(isFirefox)
            {
                return true;
            }
			
			var isEdge = agent.indexOf("edge") != -1;
			if(isEdge)
            {
                return true;
            }
			
            var isChrome = agent.indexOf("chrome") != -1;
            if(isChrome)
            {
				return true;
            }
            return false;
        }
        catch(e)
        {
			WriteLog("IsNeedCustomizedProtocol exception: " + e.message);
        }
        return true;    
    }
}